﻿using System.Collections.Generic;
using System.Xml.Serialization;

namespace Flowertwig.Utils.Entities
{
    public class Properties<TKey, TValue>
    {
        protected SortedList<TKey, TValue> _internalList;

        #region Constructors
        public Properties()
        {
            _internalList = new SortedList<TKey, TValue>();
        }
        public Properties(Properties<TKey, TValue> pList)
        {
            _internalList = new SortedList<TKey, TValue>(pList._internalList);
        }
        public Properties(IComparer<TKey> comparer)
        {
            _internalList = new SortedList<TKey, TValue>(comparer);
        }
        public Properties(IDictionary<TKey, TValue> dictionary)
        {
            _internalList = new SortedList<TKey, TValue>(dictionary);
        }
        public Properties(int capacity)
        {
            _internalList = new SortedList<TKey, TValue>(capacity);
        }
        public Properties(IDictionary<TKey, TValue> dictionary, IComparer<TKey> comparer)
        {
            _internalList = new SortedList<TKey, TValue>(dictionary, comparer);
        }
        public Properties(int capacity, IComparer<TKey> comparer)
        {
            _internalList = new SortedList<TKey, TValue>(capacity, comparer);
        }
        #endregion
        #region Properties
        // Summary:
        //     Gets or sets the number of elements that the underlaying System.Collections.Generic.SortedList<TKey,TValue>
        //     can contain.
        //
        // Returns:
        //     The number of elements that the underlaying System.Collections.Generic.SortedList<TKey,TValue>
        //     can contain.
        //
        // Exceptions:
        //   System.ArgumentOutOfRangeException:
        //     System.Collections.Generic.SortedList<TKey,TValue>.Capacity is set to a value
        //     that is less than System.Collections.Generic.SortedList<TKey,TValue>.Count.
        [XmlAttribute(AttributeName = "Capacity")]
        public int Capacity
        {
            get { return _internalList.Capacity; }
            set { _internalList.Capacity = value; }
        }
        //
        // Summary:
        //     Gets the System.Collections.Generic.IComparer<T> for the sorted list.
        //
        // Returns:
        //     The System.IComparable<T> for the current System.Collections.Generic.SortedList<TKey,TValue>.
        public IComparer<TKey> Comparer { get { return _internalList.Comparer; } }
        //
        // Summary:
        //     Gets the number of key/value pairs contained in the System.Collections.Generic.SortedList<TKey,TValue>.
        //
        // Returns:
        //     The number of key/value pairs contained in the System.Collections.Generic.SortedList<TKey,TValue>.
        public int Count { get { return _internalList.Count; } }
        //
        // Summary:
        //     Gets a collection containing the keys in the System.Collections.Generic.SortedList<TKey,TValue>.
        //
        // Returns:
        //     A System.Collections.Generic.IList<T> containing the keys in the System.Collections.Generic.SortedList<TKey,TValue>.
        public IList<TKey> Keys
        {
            get { return _internalList.Keys; }
        }
        //
        // Summary:
        //     Gets a collection containing the values in the System.Collections.Generic.SortedList<TKey,TValue>.
        //
        // Returns:
        //     A System.Collections.Generic.IList<T> containing the keys in the System.Collections.Generic.SortedList<TKey,TValue>.
        public IList<TValue> Values
        {
            get { return _internalList.Values; }
        }

        // Summary:
        //     Gets or sets the value associated with the specified key.
        //
        // Parameters:
        //   key:
        //     The key whose value to get or set.
        //
        // Returns:
        //     The value associated with the specified key. If the specified key is not
        //     found, attempting to get it returns the default value for the value type
        //     TValue, and attempting to set it creates a new element using the specified
        //     key.
        //
        // Exceptions:
        //   System.ArgumentNullException:
        //     key is null.
        //
        //   System.Collections.Generic.KeyNotFoundException:
        //     The property is retrieved and key does not exist in the collection.
        public TValue this[TKey key]
        {
            get { return _internalList[key]; }
            set { _internalList[key] = value; }
        }

        #endregion
        #region Functions
        public void Add(TKey key, TValue value) { _internalList.Add(key, value); }
        public void Clear() { _internalList.Clear(); }
        public bool ContainsKey(TKey key) { return _internalList.ContainsKey(key); }
        public bool ContainsValue(TValue value) { return _internalList.ContainsValue(value); }
        //public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator() { return list.GetEnumerator(); }
        //IEnumerator IEnumerable.GetEnumerator()
        //{
        //    return list.GetEnumerator();
        //}
        public int IndexOfKey(TKey key) { return _internalList.IndexOfKey(key); }
        public int IndexOfValue(TValue value) { return _internalList.IndexOfValue(value); }
        public bool Remove(TKey key) { return _internalList.Remove(key); }
        public void RemoveAt(int index) { _internalList.RemoveAt(index); }
        public void TrimExcess() { _internalList.TrimExcess(); }
        public bool TryGetValue(TKey key, out TValue value) { return _internalList.TryGetValue(key, out value); }
        #endregion
        #region Own functions
        public void Set(TKey key, TValue obj)
        {
            _internalList.Remove(key);
            _internalList.Add(key, obj);
        }

        public TValue Get(TKey key)
        {
            TValue obj;
            _internalList.TryGetValue(key, out obj);
            return obj;
        }
        #endregion

        [XmlArray(IsNullable = true, ElementName = "Items")]
        [XmlArrayItem(ElementName = "Item")]
        public PropertyItems<TKey, TValue> Items
        {
            get { return new PropertyItems<TKey, TValue>(ref _internalList); }
            set
            {
                if (value != null)
                {
                    _internalList = value._internalList;
                }
            }
        }

        #region XmlSeralization
        [XmlIgnore]
        public bool CapacitySpecified
        {
            get { return Capacity != 4; }
            set { }
        }
        [XmlIgnore]
        public bool ItemsSpecified
        {
            get { return _internalList.Count > 0; }
            set { }
        }
        #endregion
    }
}
